home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Magnum One
/
Magnum One (Mid-American Digital) (Disc Manufacturing).iso
/
d18
/
turbcomm.arc
/
TC.PAS
< prev
Wrap
Pascal/Delphi Source File
|
1989-06-30
|
31KB
|
812 lines
{ File: TC.PAS }
Program TurboComm;
{ Program's function: Test out COMMLIB.INC }
{ Some code has been added that will only compile under }
{ Turbo Pascal Version 3.0 or greater }
{ Search for 'Version 3.0', comment that code out, and }
{ un-comment out the code marked '< 3.0' }
{ Turn off ^C checking, to enhance speed somewhat }
{$C-}
Label EndProgram;
Const
ProgramName = 'TurboComm';
KeyFileName : String[80] = 'TC';
ProgramVer = '1.2';
Esc = ^[;
CarrReturn = ^M;
ReverseScreen = ^['[?5h';
UnreverseScreen = ^['[?5l';
SaveCursor = ^['7';
RestoreCursor = ^['8';
Bold = ^['[1m';
Off = ^['[m';
Reverse = ^['[7m';
ReverseBold = ^['[7;1m';
PrinterReady = ^['[?10n'; { Printer is turned on }
PrinterNotReady = ^['[?11n'; { Printer if not turned on }
TermVT102 = ^['[?6c';
TermVT125 = ^['[?12;7;0c';
TermVT220 = ^['[?62;1;2c';
TermVT240 = ^['[?62;1;2;3;4c';
SendRetries = 10; { Max number of times to resend a char }
VT200Keys : Boolean = True; { Use the VT2xx function key values }
FileNameLen = 62; { Turbo Pascal Version 3.0 Only }
{ i.e. It supports pathnames }
{ FileNameLen = 14; { Turbo Pascal Version < 3.0 }
Type
STR80 = String[80];
StringLong = String[150];
Var
DummyLogical : Boolean;
Counter, Counter2, CurrentBaud, CtrlCCheck : Integer;
TermID : STR80; { String returned on host after Terminal ID request }
FKey_Dir : Str80; { Modification for V1.2 - FKey_Dir }
FileOpen : Boolean;
ReGISOn : Boolean; { Are we running the Poly-ReGIS emulator? }
DisplayOn : Boolean; { Output to screen? }
PrinterOn : Boolean; { Output to printer? }
LoggingOn : Boolean; { Output to file? }
FileVar : Text; { File type for sending or receiving }
Filename : String[FileNameLen];
CursorRow, CursorCol : Integer; { Supplied by GetCursorPosition }
{ These are the different data registers used for MSDOS interrupts }
Type
__Regs = Record case Integer of
1: (AX,BX,CX,DX,BP,SI,DI,DS,ES,Flags : INTEGER);
2: (AL,AH,BL,BH,CL,CH,DL,DH : Byte);
end;
Var
__Registers : __Regs;
__SaveRegisters : __Regs; { Use this to save the initial reg values }
{$I FUNKEY.INC } { Include function key input definiton }
Procedure WriteStatus(OutputString : StringLong);
{ Get current cursor position, write status on bottom of screen,
return to previous cursor position }
Begin
Write(SaveCursor); { Save cursor position }
GotoXY(1,24);
ClrEol;
Write(OutputString);
Write(RestoreCursor); { Restore cursor position }
End; { Procedure WriteStatus }
Procedure SetCtrlCCheck;
{ Read startup value of Control-C checking, set off, save value }
{ N.B. This is the equivalent of the MS-DOS BREAK=OFF command }
{ and is required to run this program. }
Begin
{ Get initial value and save to variable }
__Registers.AH := $33;
__Registers.AL := 0;
Intr($21,__Registers);
CtrlCCheck := __Registers.DL;
{ Set checking off }
__Registers.AH := $33;
__Registers.AL := 1;
__Registers.DL := 0;
Intr($21,__Registers);
End; { Procedure SetCtrlCCheck }
Procedure ResetCtrlCCheck;
{ Reset the original Control C checking value to startup value }
{ See previous procedure for explaination. }
Begin
__Registers.AH := $33;
__Registers.AL := 1;
__Registers.DL := CtrlCCheck;
Intr($21,__Registers);
End; { Procedure ResetCtrlCCheck }
Function CheckPrinter : Boolean;
{ Check the status of the printer port }
Begin
If Port[$43] = 100
Then CheckPrinter := True
Else CheckPrinter := False;
End; { Function CheckPrinter }
Procedure CheckFunctionStatus(FunctionStatus : Boolean;
FunctionName : STR80);
{ Check the status of a function's value, and print on error,
given the name of the function that was called. }
Var
OutputLine : STR80;
Begin
If Not FunctionStatus
Then
Begin
OutputLine := Bold+FunctionName+' not successful.'+Off;
WriteStatus(OutputLine);
End { If file not opened }
End; { Procedure CheckFunctionStatus }
{$I COMMLIB.INC } { Include communications function definitions }
{$I CHECKESC.INC } { Check all escape sequences for specials }
{$I GETVIDLN.INC } { Read video memory for screen line }
{$I GETENV.INC } { Procedure to get MS-DOS environmental variable }
{$I REDEFINE.INC } { Include function key redefinition routines }
Procedure PrintScreen;
{ Read the current screen from video memory, and dump to printer }
{ N.B. If ReGIS is running, let it handle print screens itself }
Var
VidChar : Char;
LineCounter, ColCounter : Integer;
VideoString,DummyString : StringLong;
LineDrawingOn : Boolean;
Begin
If CheckPrinter And (Not ReGISOn) { The printer is ready }
Then { and we're not running ReGIS }
Begin
{ First set up video screen width by getting a line twice }
DummyString := GetVidLine(1);
DummyString := GetVidLine(1);
{ Now set printer width according to screen width }
If VideoScreenWidth = 132
Then Write(Lst,^[,'[4w')
Else Write(Lst,^[,'[0w');
LineDrawingOn := False;
Write(Lst,^O); { Turn printer graphics off }
{ Now get all the screen lines and print them }
Write(ReverseScreen); { Reverse the screen until done }
For LineCounter := 1 to 24 Do
Begin
VideoString := GetVidLine(Linecounter); { Get line }
{ Move source code left, because of length of lines }
For ColCounter := 1 to Length(VideoString) Do
Begin { Checking and printing character }
VidChar := VideoString[ColCounter];
If Ord(VidChar) < 32
Then { We've got a graphics character to print }
If LineDrawingOn
Then Write(Lst,Chr(Ord(VidChar) + 95))
Else Begin
Write(Lst,^N); { Printer to graphics mode }
Write(Lst,Chr(Ord(VidChar) + 95));
LineDrawingOn := True;
End { We had to turn on graphics mode }
Else If Not LineDrawingOn
Then Write(Lst,VidChar) { normal character }
Else Begin
Write(Lst,^O);
Write(Lst,VidChar);
LineDrawingOn := False;
End; { We had to turn off graphics & print }
End; { FOR ColCounter loop to print video line }
Writeln(Lst); { Send a carriage return, line feed to printer }
Delay(2); { Give it a short rest }
End; { FOR LineCounter loop to print video line }
Write(UnReverseScreen);
Write(Lst,^O); { Always turn line drawing off when done }
End;
End; { Procedure PrintScreen }
{ Const { Turbo Pascal Version < 3.0 }
{ ParamStrArray : Array[1..5] of STR80 = ('','','','',''); { nulls }
{ Var { Turbo Pascal Version < 3.0 }
{ ParamCount : Byte;
{ Procedure ParseCmdLine; { Turbo Pascal Version < 3.0 }
{ Read any user command line, and return it as a string }
{ This loads the array ParamStrArray }
{ Var
CL : STR80 absolute cseg:$80;
CLCopy : STR80;
begin
ParamCount := 0;
CLCopy := CL;
While CLCopy > '' Do
Begin
While CLCopy[1] = ' ' Do
CLCopy := Copy(CLCopy,2,Length(CLCopy) - 1);
ParamCount := ParamCount + 1;
While (CLCopy[1] <> ' ') And (CLCopy > '') Do
Begin
ParamStrArray[ParamCount] := ParamStrArray[ParamCount]
+ CLCopy[1];
CLCopy := Copy(CLCopy,2,Length(CLCopy) - 1);
End; { While the next char isn't a space }
{ End; { While there are more characters to get }
{ end; { Procedure ParseCmdLine }
{ Function ParamStr(I : Byte) : STR80; { Turbo Pascal Version < 3.0 }
{ Given the index number, return the parameter string from the array }
{ Begin
ParamStr := ParamStrArray[I];
End; { Function ParamStr }
Function DisplayMenu : Boolean;
{ Check command line for 'T' --> go directly to terminal emulation }
{ (i.e. don't display opening menu }
{ Also check for initial baud rate setting }
Type
ValidBaudType = Array [1..8] of String[4];
Const
NumBauds = 8;
ValidBaud : ValidBaudType = ('110','150','300',
'600','1200','2400',
'4800','9600');
Var
Counter,BaudIndex : Integer;
TempStr : STR80;
Begin
DisplayMenu := True;
CurrentBaud := DefaultBaud;
VT200Keys := True;
{ Read through command line for valid input parameters }
For Counter := 1 to ParamCount Do
Begin
TempStr := ParamStr(Counter);
If UpCase(TempStr[1]) = 'T'
Then DisplayMenu := False
Else If (TempStr = 'VT100') Or
(TempStr = 'vt100')
Then VT200Keys := False
Else If TempStr[1] = '@'
Then KeyFileName := Copy(TempStr,2,80)
Else
{ Compare ParamStr against valid baud rates }
For BaudIndex := 1 to NumBauds Do
If TempStr = ValidBaud[BaudIndex]
Then Val(TempStr,CurrentBaud,Counter2);
End; { For Counter loop }
End; { Function DisplayMenu }
Function MSDosVersion : Real;
{ Return the current MS-DOS version number }
begin
__Registers.AX := $3000;
MSDos( __Registers );
MSDosVersion := __Registers.AL + __Registers.AH/100;
end; { Function MSDosVersion }
Procedure WriteScr(Var CharToPrint : Char);
{ Write a character to the screen }
{ This could be replaced by the standard Write statement, but }
{ it runs about 5 percent faster. }
{ Save and restore the values of the registers }
Begin
__SaveRegisters := __Registers;
With __Registers Do Begin
CX := 0;
DI := 0; { Function code for Console Out }
AL := Ord(CharToPrint);
End;
Intr(24,__Registers);
__Registers := __SaveRegisters;
End; { Procedure WriteScr }
Procedure DisplayHelp;
{ Display help text on the screen }
Var
OutputLine : StringLong;
OldVideoLine : StringLong; { Old value of 24th line Declaration }
Begin
OutputLine := Off+'Press '+Bold+'<F4>'+Off+
' for command mode: '+Bold+
'C'+Off+'lose '+Bold+
'D'+Off+'isconnect '+Bold+
'P'+Off+'rinter '+Bold+
'Q'+Off+'uit '+Bold+
'R'+Off+'eceive '+Bold+
'S'+Off+'end '+
'e'+Bold+'X'+Off+'it';
OldVideoLine := GetVidLine(24); { Old value of 24th line assignment }
WriteStatus(OutputLine);
End; { Procedure DisplayHelp }
Procedure InitTermID;
{ Initialize the global variable TermID, based on whether we're running
ReGIS emulation software or operating in normal mode. }
Var
InputString : STR80;
Begin
ReGISOn := False;
InputString := '';
Write(Esc,'PpR(p)',Esc,'\'); { Send out ReGIS report request }
{ ReGIS should return something like '[0,0]'. If ReGIS isn't on, }
{ nothing should be returned. So just check for the standard chars }
For Counter := 1 to 50 Do
If ReadKey
Then
InputString := InputString + InString;
If Pos(']',InputString) > 0
Then Begin
ReGISOn := True;
If VT200Keys
Then { Graphics and VT200 Class }
TermID := TermVT240
Else { Graphics and VT100 Class }
TermID := TermVT125;
End
Else Begin
ReGISOn := False;
If VT200Keys
Then { No Graphics and VT200 Class }
TermID := TermVT220
Else { No Graphics and VT100 Class }
TermID := TermVT102;
End;
ClrScr;
End;
Function Space(X : Byte) : STR80;
{ BASIC-like function to return x number of spaces }
Var
TempString : STR80;
Counter : Integer;
Begin
TempString := '';
For Counter := 1 to X Do TempString := TempString + ' ';
Space := TempString;
End; { Function Space }
Function MoveLeft(X : Integer) : STR80;
{ Move the cursor left X number of positions }
Var
TempString : STR80;
Begin
Str(X,TempString);
MoveLeft := ^[ + '[' + TempString + 'D';
End; { Function MoveLeft }
Procedure CloseFile;
{ When done receiving text file, close it }
Var
OldVideoLine : StringLong; { Old value of 24th line Declaration }
Begin
If FileOpen Then
Begin
Write(SaveCursor);
Close(FileVar);
OldVideoLine := GetVidLine(24);
GotoXY(1,24);
ClrEol;
NormVideo;
Write('Closing any open files');
LowVideo;
Delay(1000);
GotoXY(1,24);
ClrEol;
Write(OldVideoLine); { Restore old value of 24th line }
Write(RestoreCursor);
FileOpen := False;
LoggingOn := False;
End;
End; { Procedure CloseFile }
Procedure SendFile;
{ Send a text file from disk via comm line }
Var
Line : StringLong;
OldVideoLine : StringLong; { Old value of 24th line Declaration }
Counter : Byte;
Begin
{ First check that a file isn't already open }
If FileOpen Then
Begin
CloseFile;
FileOpen := False;
End; { If they had a file open }
OldVideoLine := GetVidLine(24); { Old value of 24th line assignment }
Write(ReverseScreen); { Give screen white background }
NormVideo;
{ Print prompt, then back up for filename input }
Write(SaveCursor); { Save the current cursor position }
GotoXY(1,24);
ClrEol;
Write(ReverseBold,'File to send: ',Space(FileNameLen),
MoveLeft(FileNameLen));
{ This procedure breaks the rule that says you shouldn't mix }
{ level 1 console input with level 2 console input (Read()s) }
Read(FileName);
GotoXY(1,24);
ClrEol;
LowVideo;
Write(OldVideoLine); { Restore old value of 24th line }
Write(RestoreCursor); { Restore cursor position from save }
LowVideo;
Write(UnreverseScreen);
ClearLevel2Buffer; { clear level 2 keyboard buffer }
Assign(FileVar, FileName);
{$i-} Reset(FileVar); {$i+}
If IOResult = 0 then
Begin
FileOpen := True;
While Not Eof(fileVar) Do
Begin
Read(FileVar,Line);
For Counter := 1 to Length(Line) Do Begin
Counter2 := 0; { Initialize # times sent counter }
While (Not WriteCommChar(Line[Counter])) And
(Counter2 < SendRetries) Do
Begin
Counter2 := Counter2 + 1;
Delay(10);
End; { if you couldn't send that character }
If ReadCommChar Then WriteScr(CommIn.Char);
End; { print line a character at a time }
DummyLogical := WriteCommChar(CarrReturn);
While ReadCommChar Do WriteScr(CommIn.Char);
Readln(FileVar);
End;
End { If file exists }
Else
WriteStatus(^G+^G+Bold+'File not found'+Off);
CloseFile;
End; { Procedure SendFile }
Procedure ReceiveFile;
Var
OldVideoLine : StringLong; { Old value of 24th line Declaration }
{ Log the data coming in from the host to a file }
Begin
OldVideoLine := GetVidLine(24); { Old value of 24th line assignment }
Write(ReverseScreen); { Give screen white background }
NormVideo;
Write(SaveCursor); { Save current cursor position }
GotoXY(1,24);
ClrEol;
{ Print prompt, then back up for filename input }
Write(ReverseBold,'File to Receive: ',Space(FileNameLen),
MoveLeft(FileNameLen));
{ This procedure breaks a rule that says you shouldn't mix }
{ level 1 console input with level 2 console input (Read()s) }
Read(FileName);
GotoXY(1,24);
ClrEol;
LowVideo;
Write(OldVideoLine); { Restore old value of 24th line }
Write(RestoreCursor); { Restore cursor position from save }
LowVideo;
Write(UnReverseScreen); { Return screen to white on black }
Assign(FileVar,FileName);
{$i-} Rewrite(FileVar); {$i+}
If IOResult <> 0
Then
Begin
Writeln;
WriteStatus(^G+^G+Bold+'File could not be opened!'+Off);
End
Else
Begin
FileOpen := True;
LoggingOn := True;
End; { If file could be opened }
ClearLevel2Buffer; { clear level 2 keyboard buffer }
End; { Procedure ReceiveFile }
Procedure TestKeystroke;
{ They've hit F4, so they want a special function. }
{ Get the next keystroke to determine the function. }
Begin
{ Don't come back til you've got a keystroke }
While Not ReadKey Do;
{ Translate keystroke }
If Length(InString) = 1 { it wasn't a function key }
Then Case UpCase(InString[1]) Of
'C': CloseFile;
'D': CheckFunctionStatus(DisconnectModem,'Disconnecting');
'P': PrinterOn := Not PrinterOn; { Toggle printer mode }
'Q': Begin
DummyLogical := DisconnectModem;
Write(CarrReturn,Bold,'Disconnecting ');
FunCode := Dum100; { Exit Program }
End; { They pressed 'Q' }
'R': ReceiveFile;
'S': SendFile;
'X': FunCode := Dum100; { Exit program, trips Until }
Else { Display help text }
DisplayHelp;
End { Check keystroke }
Else If (FunCode In Redefinables) { in set of redefinable keys }
Then RedefineKey(FunCode)
Else WriteStatus('That function key may not be redefined.');
End; { Procedure TestKeystroke }
Function StartupDisplay : Boolean;
{ Display initial help information for TurboComm program }
{ and wait until they press either Do or Exit Key }
Const
StartingCol = 20;
Var
ValidKey : Boolean;
Begin
{ Display help text }
ClrScr;
NormVideo;
GotoXY(16,1);
Write(^[,'#3',ProgramName); { Double size - top half }
GotoXY(16,2);
Write(^[,'#4',ProgramName); { Double size - bottom half }
GotoXY(19,3);
Write('Rainbow MS-DOS Terminal Emulation Software');
LowVideo;
GotoXY(29,4);
Write('Public Domain software');
GotoXY(22,5);
Write('by Stew Stryker, RONNIE Support Group');
GotoXY(10,7);
Write('Press ',Bold,'<DO>',Off,' for terminal emulation',Off);
GotoXY(16,8);
Write(Bold,'<HELP>',Off,' for additional information');
GotoXY(16,9);
Write(Bold,'<EXIT>',Off,' to exit to operating system');
GotoXY(15,12);
Write(^[,'[4m','Immediate Commands while in terminal emulation',Off);
GotoXY(1,13);
Write(Bold,'<F4>',Off,' followed by highlighted character:');
GotoXY(StartingCol,14);
Write(Bold,'C',Off,'lose open file');
GotoXY(StartingCol,15);
Write(Bold,'D',Off,'isconnect modem');
GotoXY(StartingCol,16);
Write(Bold,'P',Off,'rinter toggle on/off');
GotoXY(StartingCol,17);
Write(Bold,'Q',Off,'uit, disconnect & exit');
GotoXY(StartingCol,18);
Write(Bold,'R',Off,'eceive a file');
GotoXY(StartingCol,19);
Write(Bold,'S',Off,'end a file');
GotoXY(StartingCol,20);
Write('e',Bold,'X',Off,'it to operating system');
GotoXY(StartingCol,21);
Write('any other character displays a short help message');
GotoXY(10,7);
{ Wait until they hit a valid key }
ValidKey := False;
While Not ValidKey Do
Begin
While Not ReadKey Do; { Wait for any keystroke }
If (FunCode <> KDo) And (FunCode <> KExit)
Then
If FunCode = Help
Then Begin{ Display disclaimer information }
GotoXY(1,5);
Write(^[,'[J'); { Clear to end of screen }
GotoXY(35,6);
Writeln(^[,'[4m','DISCLAIMER',^[,'[m');
Writeln;
Writeln(^[,'[7C','The author and Digital Equipment Corp absolve themselves of any');
Writeln(^[,'[7C','possible warranties as to the capabilities of this program, and');
Writeln(^[,'[7C','specifically disclaim any implied warranties of effectiveness.');
Writeln(^[,'[7C','This product is provided "as is" and should not be considered a');
Writeln(^[,'[7C','"Digital-supported" product.');
Writeln;
Writeln(^[,'[7C','This program is donated to the public domain. It may be copied');
Writeln(^[,'[7C','and disseminated freely for non-profit purposes, if and only if');
Writeln(^[,'[7C','this disclaimer is included.');
End { If they pressed Help }
Else
Begin
GotoXY(1,24);
Write(^G,^G);
Write(Reverse,'Press ',Bold,'<DO>',Off,
Reverse,' to start terminal emulation, or ',
Bold,'<EXIT>',Off,Reverse,' to exit program',
Off);
GotoXY(10,7);
End
Else { They pressed Do or Exit }
ValidKey := True;
End; { Waiting until they hit a valid key }
If FunCode = KDo
Then StartupDisplay := True
Else StartupDisplay := False;
End; { Function StartupDisplay }
Begin { Main program }
If MSDosVersion < 2.05 { This program requires 2.05 or greater }
Then
Begin
NormVideo;
Writeln(^G,^G,'This program requires MS-DOS 2.05 or higher!!');
Goto EndProgram;
End;
SetCtrlCCheck; { Read startup CtrlC checking value, and set off }
{ Read the current comm settings from the non-volatile memory }
CheckFunctionStatus(ReadCurrentCommSettings,
'Reading Current Comm Settings');
FKey_Dir := 'TC_DIR'; { Modification for V1.2 - FKey_Dir }
{ Initialize comm port, function keys, escape sequence test, & Term ID }
DummyLogical := ReplaceDefault; { These work, even though they }
DummyLogical := InitPort; { return False. }
InitFunkeys; { Define the initial value for function keys }
InitTermID; { Check if we're running in ReGIS }
{ Display help text and either run or exit program }
If DisplayMenu { Don't by-pass initial menu }
Then If Not StartupDisplay { Abort program }
Then Goto EndProgram;
ReadKeyFile; { Read in any function key redefinitions }
CheckFunctionStatus(SetSerial(3,CurrentBaud,DefaultStopBits,
DefaultDataBits,DefaultParity,Chr(0)),
'Setting Baud Rate');
InitEscSeq; { Define escape sequences to trap }
PrinterOn := False;
DisplayOn := True;
FileOpen := False;
LoggingOn := False;
CrtInit; { Display sign-on message }
ClrScr;
Write('Baud rate: ');
NormVideo;
Writeln(CurrentBaud);
GotoXY(26,1);
LowVideo;
Write('On-Line with ');
NormVideo;
Write(ProgramName,' ');
LowVideo;
Writeln('(',ProgramVer,')');
GotoXY(66,1);
If ReGISOn
Then If VT200Keys
Then Write('VT240')
Else Write('VT125')
Else If VT200Keys
Then Write('VT220')
Else Write('VT102');
Writeln(' emulation');
Repeat { Keep reading/writing until <F4> is pressed }
{ Check if a character came in the comm port, then display it. }
IF ReadCommChar Then
{ If ESC was received, test for special sequences }
If CommIn.Char = Esc
Then CheckEscSeq
Else { Check if output goes to printer, screen, or both }
Begin
If DisplayOn And Not PrinterOn
Then WriteScr(CommIn.Char)
Else If (Not DisplayOn) And PrinterOn
{ i.e. Printer only }
Then Write(Lst,CommIn.Char)
Else Begin
WriteScr(CommIn.Char);
PrintChar(CommIn.Char);
End; { both display and print }
If LoggingOn Then Write(FileVar,CommIn.Char);
End; { If it wasn't an escape sequence }
{ Get the keyboard character and send it out the comm port. }
If ReadKey Then
{ Check if a Function key was pressed }
If Funcode <> DUM4 { (i.e. Funcode not dummy value) }
Then Case Funcode Of
BREAK: DummyLogical := SendBreak;
{ Send a Break for
250 milliseconds }
F4: TestKeystroke; { Special Function desired ? }
PRINT: If FunShiftCode AND 4 = 4 { Held down Ctrl key}
Then PrinterOn := Not PrinterOn
Else PrintScreen;
else WriteCommString(InString);
End { Case of Funcode }
Else
If VT200Keys And (FunShiftCode AND 4 = 0)
{ They hit a F11 - F13 while emulating a VT2xx }
Then Case InString[1] Of
^[: WriteCommString(^[+'[23~'); { Esc }
^H: WriteCommString(^[+'[24~'); { BS }
^J: WriteCommString(^[+'[25~'); { Lf }
Else WriteCommString(InString);
End { Case statement }
Else WriteCommString(InString); {if not in ReGIS}
Until FunCode = DUM100; { They said to quit }
CloseFile; { Close any open files. }
DummyLogical := ReplaceDefault; { Replace default comm port values }
WriteKeyFile; { If a function key def has changed, check saving it }
ResetCtrlCCheck; { Restore original value }
Writeln(Bold,'Returning to MS-DOS operating system',Off);
CrtExit;
EndProgram:
End.